/** CS2340 40 Jiggawatt Hard Driver Project
 *  Suk Hwan Hong
 *  Rhys Saraceni
 *  Travis Cooper
 *  Luke Stubb
 */

// $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString, numericLiterals
package edu.gatech.jiggawatt.office.presenter;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;

import edu.gatech.jiggawatt.office.model.Admin;
import edu.gatech.jiggawatt.office.model.Patient;
import edu.gatech.jiggawatt.office.model.Nurse;
import edu.gatech.jiggawatt.office.model.Doctor;
import edu.gatech.jiggawatt.office.model.User;
import edu.gatech.jiggawatt.office.model.Database;


/**
 * @author 40 Jiggawatt Hard Driver
 * @version 1.0 
 */
public class Presenter {
	// will be implemented using socket programming later
	/**
	 * Field serverIP.
	 */
	private String serverIP; // $codepro.audit.disable variableShouldBeFinal
	
	/**
	 * Field serverPort.
	 */
	private String serverPort; // $codepro.audit.disable variableShouldBeFinal
	
	/**
	 * Field database.
	 */
	private Database database; // $codepro.audit.disable variableShouldBeFinal
	
	/**
	 * Constructor for Presenter.
	 * @param serverIP String
	 * @param serverPort String
	 */
	public Presenter(String serverIP, String serverPort) {
		this.serverIP = serverIP;
		this.serverPort = serverPort;
		database = new Database();
		
		//Default users for demo purpose
		database.addUser(new Admin("Admin", "1234", "Bob", "Waters"));
		database.addUser(new Patient("Patient", "1234", "Some", "Guy"));
		database.addUser(new Nurse("Nurse", "1234", "Some", "Guy"));
		database.addUser(new Doctor("Doctor", "1234", "Some", "Guy"));
	}

	/**
	 * Returns -1 if fails, userType if it succeeds, or 4 if account is locked
	 * @param id String
	 * @param pw String
	 * @return int
	 */
	public int login(String id, String pw) {
		final User user = database.getUser(id);
		
		if (user == null) {
			return -1;
		}
		
		if (user.isSuspended()) {
			return 4;
		}
		
		if (user.checkPassword(pw) == true) { // $codepro.audit.disable equalityTestWithBooleanLiteral
			user.clearFailedLogin();
			return user.getUserType();
		}
		
		user.incFailedLogin();
		return -1;
	}
	
	/**
	 * add user to the database
	 * @param user User
	 */
	public void addUser(User user) {
		database.addUser(user);
	}
	
	/**
	 * get user from the database
	 * @param id String
	 * @return User
	 */
	public User getUser(String id) {
		return database.getUser(id);
	}
	
	/**
	 * remove user from the database
	 * @param id String
	 * @return boolean
	 */
	public boolean removeUser(String id) { // $codepro.audit.disable booleanMethodNamingConvention
		return database.removeUser(id);
	}
	
	/**
	 * get list of users from database
	 * @return List<User>
	 */
	public List<User> getUserList() {
		return database.getUserList();
	}
	
	/**
	 * get patient from database
	 * @param fullName String
	 * @return Patient
	 */
	public Patient getPatient(String fullName) {
		return database.getPatient(fullName);
	}
	
	/**
	 * save database
	 * @param filename String
	 */
	public void save(String filename) {
		try {
			final ObjectOutputStream out = new ObjectOutputStream( // $codepro.audit.disable closeWhereCreated
					new FileOutputStream(filename));
			out.writeObject(database);
		} catch (FileNotFoundException e) {
			System.err.println("Failed to open file " + filename + " for output");
			e.printStackTrace();
		} catch (IOException e) {
			System.err.println("Failed during save for unknown reason");
			e.printStackTrace();
		}
	}
	
	/**
	 * load database
	 * @param filename String
	 */
	public void load(String filename) {
		try {
			final ObjectInputStream in = new ObjectInputStream( // $codepro.audit.disable closeWhereCreated
					new FileInputStream(filename));
			this.database = (Database) in.readObject();
		} catch (FileNotFoundException e) {
			System.err.println("Could not find file " + filename + " for opening");
			e.printStackTrace();
		} catch (IOException e) {
			System.err.println("Other input failure during object read");
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			System.err.println("Failed to find class type on object read");
			e.printStackTrace();
		}
	}
}
